package com.yuantu.judiciary.serviceimpl;

import cn.hutool.core.codec.Base64Encoder;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.extra.qrcode.QrCodeUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.google.gson.Gson;
import com.yuantu.judiciary.constant.Regulation;
import com.yuantu.judiciary.dao.*;
import com.yuantu.judiciary.exception.enums.AccountExceptionEnum;
import com.yuantu.judiciary.exception.enums.CheckPersonExceptionEnum;
import com.yuantu.judiciary.exception.enums.OrganizationExceptionEnum;
import com.yuantu.judiciary.model.domain.*;
import com.yuantu.judiciary.model.dto.*;
import com.yuantu.judiciary.model.enums.*;
import com.yuantu.judiciary.model.form.*;
import com.yuantu.judiciary.model.vo.*;
import com.yuantu.judiciary.model.word.WordMaker;
import com.yuantu.judiciary.model.word.WordParagraph;
import com.yuantu.judiciary.model.word.WordText;
import com.yuantu.judiciary.service.*;
import com.yuantu.judiciary.utils.AssertUtil;
import com.yuantu.judiciary.utils.PageUtil;
import com.yuantu.judiciary.utils.TimeUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.impl.xb.xmlschema.SpaceAttribute;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.math.BigInteger;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 个人尽调接口实现
 *
 * @author syw
 * @since 2023-07-06
 **/
@Service
@Slf4j
@RequiredArgsConstructor
public class CheckPersonServiceImpl implements ICheckPersonService {

    private static final Gson GSON = new Gson();
    private final IQueryRecordDao queryRecordDao;
    private final IQueryEntityDao queryEntityDao;
    private final IUserFollowDao userFollowDao;
    private final IAccountDao accountDao;
    private final IOrganizationDao organizationDao;
    private final ICheckResultService checkResultService;
    private final ISysFileService fileService;
    @Value("${upload.file.auth}")
    private String uploadAuthorizedPath;
    @Value("${upload.file.temp}")
    private String uploadAuthorizedTempPath;
    private final ISysFileDao fileDao;
    private final ICaseRemoveDao caseRemoveDao;
    private final IPersonRemoveDao personRemoveDao;
    private final IAuthInfoDao authInfoDao;
    private final IOrgVipRecordDao vipRecordDao;
    private final IUserService userService;
    private final IAgentService agentService;

    @Override
    public String getQueryCode(Long userId, String mark, String mode, Long id) {
        String url = "https://admin.njxnet.com/cxb/#/pages/view/code?id=" + id + "&mark=" + mark + "&mode=" + mode + "&userId=" + userId;
        return getQRCode(url);
    }

    public static String getQRCode(String url) {
        String base64Url = "data:image/png;base64,";
        BufferedImage bufferedImage = QrCodeUtil.generate(url, 300, 300);
        byte[] bytes = ImgUtil.toBytes(bufferedImage, "png");
        return base64Url + Base64Encoder.encode(bytes);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CheckPersonBriefVO getBrief(Long userId, GetQueryInfoForm form) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);
        // todo 查询人是企业账号需验证查询内容中人名与身份证号是否一致
        CheckPersonBriefVO res = new CheckPersonBriefVO();
        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String badRecordStr = checkResultService.getJsonDataProd(userId, QueryType.PER_BAD_RECORD, searchRecord, entity);
        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);
//        String limitStr = checkResultService.getJsonData(userId, QueryType.PER_LIMIT, searchRecord, entity);
//        String dishonestInfoStr = checkResultService.getJsonData(userId, QueryType.PER_DISHONEST, searchRecord, entity);

        res.setId(queryRecord.getId());
        res.setName(searchRecord.getName());
        res.setIdNumber(searchRecord.getIdNumber());

        AccountDO account = accountDao.findByIdAndDeletedFalse(queryRecord.getCreatorId());
        if (ObjectUtils.isEmpty(account)) {
            res.setCreatorName("示例发起人");
        } else {
            OrganizationDO organization = organizationDao.findByIdAndDeletedFalse(account.getOrganizationId());
            if (!ObjectUtils.isEmpty(organization)) {
                String company = OrganizationType.ENTER.equals(organization.getType()) ? organization.getEnterName() : account.getUsername();
                res.setCreatorName(company);
            } else {
                res.setCreatorName(account.getUsername());
            }
        }

        res.setCreateTime(queryRecord.getCreateTime());
        res.setAuthorizeTime(queryRecord.getAuthorizedTime());
        res.setIsIdAuthorizePass(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult())
                ? IdAuthorizeState.PASS : IdAuthorizeState.TO_VERIFY);
        UserFollowDO follow = userFollowDao.findByEntityIdAndCreatorIdAndDeletedFalse(queryRecord.getEntityId(), userId);
        res.setIsFollow(!ObjectUtils.isEmpty(follow));

        if (StringUtils.isNotBlank(badRecordStr)) {
            List<ResBadRecordDTO> data = JSON.parseArray(badRecordStr, ResBadRecordDTO.class);
            ResBadRecordDTO personResult = data.get(0);
            res.setBadRecordNum(BadRecordRiskLevelType.fromValue(StringUtils.isBlank(personResult.getRisk()) ? "" : personResult.getRisk()));
        }

        if (StringUtils.isNotBlank(judicialStr)) {
            List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                    collect(Collectors.toList());
            int criminalRecordNum = 0;
            int litigationRecordNum = 0;

            List<ResJudicialDataProdDTO> data = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
            ResJudicialDataProdDTO judicialResult = data.get(0);
            Map<String, List<CaseDataDTO>> detailMap = judicialResult.getCaseData();
            for (String category : CaseCategory.getCaseCategoryCode()) {
                List<CaseDataDTO> cases = detailMap.get(category);
                cases = cases.stream().filter(s -> !caseRemoveInfos.contains(s.getC_ah())).collect(Collectors.toList());
                int numCases = cases.size();
                if (category.equals(CaseCategory.CRIMINAL.getCode())) {
                    criminalRecordNum += numCases;
                } else {
                    litigationRecordNum += numCases;
                }
            }

            res.setCriminalRecordNum(criminalRecordNum);
            res.setLitigationRecordsNum(litigationRecordNum);

            int limitNum = Optional.ofNullable(judicialResult.getXg()).map(ResLimitDataDTO::getXgbzxr_count)
                    .map(ResLimitDataDTO.LimitCount::getCount_current).orElse(0);
            List<LimitHighDataDTO> limitHighData = Optional.ofNullable(judicialResult.getXg()).map(ResLimitDataDTO::getXgbzxr_current).orElse(new ArrayList<>());
            int removeNum = 0;
            for (LimitHighDataDTO limitHighDataInfo : limitHighData) {
                if (limitHighDataInfo != null && caseRemoveInfos.contains(limitHighDataInfo.getAh())) {
                    removeNum++;
                }
            }
            limitNum = limitNum >= removeNum ? limitNum - removeNum : 0;
            res.setLimitHighNum(limitNum);

            removeNum = 0;
            int current = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_count)
                    .map(ResDishonestDataDTO.DishonestCount::getCount_current).orElse(0);
            List<DishonestDataDTO> dishonestData = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_current).orElse(new ArrayList<>());
            for (DishonestDataDTO dishonestDataInfo : dishonestData) {
                if (dishonestDataInfo != null && caseRemoveInfos.contains(dishonestDataInfo.getAh())) {
                    removeNum++;
                }
            }
            current = current >= removeNum ? current - removeNum : 0;

            res.setDishonestNum(current);
        }

//        if (StringUtils.isNotBlank(limitStr)) {
//            List<ResLimitDataDTO> data = JSON.parseArray(limitStr, ResLimitDataDTO.class);
//            Integer limitNum = Optional.ofNullable(data.get(0)).map(ResLimitDataDTO::getXgbzxr_count)
//                    .map(ResLimitDataDTO.LimitCount::getCount_current).orElse(0);
//            res.setLimitHighNum(limitNum);
//        }

//        if (StringUtils.isNotBlank(dishonestInfoStr)) {
//            List<ResDishonestDataDTO> data = JSON.parseArray(dishonestInfoStr, ResDishonestDataDTO.class);
//            Integer current = Optional.ofNullable(data.get(0)).map(ResDishonestDataDTO::getSxbzxr_count)
//                    .map(ResDishonestDataDTO.DishonestCount::getCount_current).orElse(0);
//            res.setDishonestNum(current);
//        }
        PersonRemoveDO personRemove = personRemoveDao.findInfoByIdNumber(searchRecord.getIdNumber());
        res.setIsShow(personRemove == null);
        return res;
    }

    @Override
    public String searchPersonBusiness(Long userId, Long id) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(id);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);
        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        OrgVipRecordDO vipRecordDO = vipRecordDao.findRecordByOrganizationIdAndDeletedFalse(accountDao.findByIdAndDeletedFalse(queryRecord.getCreatorId()).getOrganizationId());
        int usedCount = queryRecordDao.countDistinctByCreatorIdAndTypeAndDeletedFalse(queryRecord.getCreatorId(), SearchType.PERSONBUSINESS);
        int totalCount = vipRecordDO.getPersonBusinessTimes();
        AssertUtil.assertTrue(usedCount < totalCount, CheckPersonExceptionEnum.QUERY_PERSON_BUSINESS_USED_UP);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);
        QueryRecordDO personBusinessRecordDo = new QueryRecordDO();
        personBusinessRecordDo.setCreatorId(queryRecord.getCreatorId());
        personBusinessRecordDo.setContent("queryId:" + id);
        personBusinessRecordDo.setType(SearchType.PERSONBUSINESS);
        queryRecordDao.save(personBusinessRecordDo);
        return checkResultService.getJsonDataProd(userId, QueryType.PER_BUSINESS, searchRecord, entity);
    }

    @Override
    public PersonBusinessCheckVO searchPersonBusinessCheck(Long userId, Long id) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(id);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);
        OrgVipRecordDO vipRecordDO = vipRecordDao.findRecordByOrganizationIdAndDeletedFalse(accountDao.findByIdAndDeletedFalse(queryRecord.getCreatorId()).getOrganizationId());
        int usedCount = queryRecordDao.countDistinctByCreatorIdAndTypeAndDeletedFalse(queryRecord.getCreatorId(), SearchType.PERSONBUSINESS);
        int totalCount = vipRecordDO.getPersonBusinessTimes();
        AssertUtil.assertTrue(usedCount < totalCount, CheckPersonExceptionEnum.QUERY_PERSON_BUSINESS_USED_UP);
        PersonBusinessCheckVO vo = new PersonBusinessCheckVO();
        vo.setLeftCount(totalCount - usedCount);
        vo.setUsedCount(usedCount);
        return vo;
    }

    @Override
    public PageVO<CaseCriminalVO> searchCriminalPage(Long userId, SearchCriminalPageForm form, Pageable pageable) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);

        List<ResJudicialDataProdDTO> resJudicialData = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
        ResJudicialDataProdDTO judicialResult = resJudicialData.get(0);
        ResJudicialDataDTO.Detail detail = judicialResult.getDetail();

        // 刑事案件
        List<CaseCriminalDTO> cases = Optional.ofNullable(detail).map(ResJudicialDataDTO.Detail::getCriminal).map(ResJudicialDataDTO.Detail.Criminal::getCases).orElse(new ArrayList<>());
        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        cases = cases.stream().filter(s -> !caseRemoveInfos.contains(s.getC_ah())).collect(Collectors.toList());
        int total = cases.size();
        List<CaseCriminalVO> res = new ArrayList<>();
        List<CaseCriminalVO> queryData = new ArrayList<>();
        if (total > 0) {
            cases.forEach(data -> {
                CaseCriminalVO criminalCaseVO = new CaseCriminalVO();
                criminalCaseVO.setId(form.getId());
                criminalCaseVO.setCaseId(data.getN_ajbs());
                criminalCaseVO.setCaseNum(data.getC_ah());
                String n_laay_tree = data.getN_laay_tree();
                String[] n_laay_tree_arr = StringUtils.isNotBlank(n_laay_tree) ? n_laay_tree.split(",") : new String[0];
                criminalCaseVO.setCaseReason(n_laay_tree_arr.length > 0 ? n_laay_tree_arr[n_laay_tree_arr.length - 1] : "");
                criminalCaseVO.setLitigationStatus(data.getN_ssdw());
                criminalCaseVO.setCaseState(data.getN_ajjzjd());
                criminalCaseVO.setCaseType(data.getN_ajlx());
                criminalCaseVO.setCaseCategory(CaseCategory.CRIMINAL.getCode());
                criminalCaseVO.setSettleWay(StringUtils.isBlank(data.getN_jafs()) ? "" : data.getN_jafs());
                criminalCaseVO.setStartTime(StringUtils.isBlank(data.getD_larq()) ? "" : data.getD_larq().split("-")[0]);
                criminalCaseVO.setStartTime(StringUtils.isBlank(data.getD_jarq()) ? "" : data.getD_jarq().split("-")[0]);
                criminalCaseVO.setIsExample(false);
                res.add(criminalCaseVO);
            });

            queryData = res.stream().filter(f -> StringUtils.isBlank(form.getCaseNum()) || f.getCaseNum().contains(form.getCaseNum()))
                    .filter(f -> StringUtils.isBlank(form.getCaseReason()) || form.getCaseReason().equals(f.getCaseReason()))
                    .filter(f -> ObjectUtils.isEmpty(form.getStartTime()) || TimeUtil.transferTimeString(form.getStartTime(), Regulation.YEAR).equals(f.getStartTime()))
                    .filter(f -> ObjectUtils.isEmpty(form.getEndTime()) || TimeUtil.transferTimeString(form.getEndTime(), Regulation.YEAR).equals(f.getEndTime()))
                    .filter(f -> StringUtils.isBlank(form.getCaseState()) || form.getCaseState().equals(f.getCaseState()))
                    .filter(f -> StringUtils.isBlank(form.getCaseType()) || form.getCaseType().equals(f.getCaseType()))
                    .collect(Collectors.toList());
        }

        if (CollectionUtils.isEmpty(queryData)) {
            return new PageVO<>(0L, Collections.singletonList(new CaseCriminalVO(
                    1L, "无", "无", "无", "无", "无", "无", "无", "无", "无", "无", true
            )));
        } else {
            return new PageVO<>((long) queryData.size(), PageUtil.getPage(queryData, pageable));
        }
    }

    @Override
    public PageVO<CaseLitigationVO> searchLitigationPage(Long userId, SearchLitigationPageForm form, Pageable pageable) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);

        List<ResJudicialDataProdDTO> resJudicialData = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
        ResJudicialDataProdDTO judicialResult = resJudicialData.get(0);
        Map<String, List<CaseDataDTO>> detailMap = judicialResult.getCaseData();
        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        detailMap.forEach((key, value) -> value.removeIf(caseDataDTO -> caseRemoveInfos.contains(caseDataDTO.getC_ah())));

        List<CaseLitigationVO> res = new ArrayList<>();
        List<CaseLitigationVO> queryData;

        List<String> caseCategory = Arrays.asList(CaseCategory.JURISDICTION.getCode(), CaseCategory.PRESERVATION.getCode(),
                CaseCategory.ADMINISTRATIVE.getCode(), CaseCategory.CIVIL.getCode(), CaseCategory.IMPLEMENT.getCode(),
                CaseCategory.BANKRUPT.getCode(), CaseCategory.COMPENSATE.getCode());
        for (String category : caseCategory) {
            List<CaseDataDTO> cases = detailMap.get(category);
            if (!CollectionUtils.isEmpty(cases)) {
                buildLitigationCaseData(form, res, cases, category);
            }
        }

        queryData = res.stream().filter(f -> StringUtils.isBlank(form.getCaseNum()) || f.getCaseNum().contains(form.getCaseNum()))
                .filter(f -> StringUtils.isBlank(form.getCaseReason()) || form.getCaseReason().equals(f.getCaseReason()))
                .filter(f -> ObjectUtils.isEmpty(form.getStartTime()) || TimeUtil.transferTimeString(form.getStartTime(), Regulation.YEAR).equals(f.getStartTime().split("-")[0]))
                .filter(f -> ObjectUtils.isEmpty(form.getEndTime()) || TimeUtil.transferTimeString(form.getEndTime(), Regulation.YEAR).equals(f.getEndTime().split("-")[0]))
                .filter(f -> StringUtils.isBlank(form.getCaseState()) || form.getCaseState().equals(f.getCaseState()))
                .filter(f -> StringUtils.isBlank(form.getCaseType()) || form.getCaseType().equals(f.getCaseType()))
                .filter(f -> ObjectUtils.isEmpty(form.getCaseCategory()) || form.getCaseCategory().equals(CaseCategory.ALL) || form.getCaseCategory().getCode().equals(f.getCaseCategory()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(queryData)) {
            return new PageVO<>(0L, Collections.singletonList(new CaseLitigationVO(
                    1L, "无", "无", "无", "无", "无", "无", "无", "无", "无", "无", true
            )));
        } else {
            return new PageVO<>((long) queryData.size(), PageUtil.getPage(queryData, pageable));
        }
    }

    @Override
    public Long mySearchLitigationPage(Long userId) {
        AccountDO account = accountDao.findByIdAndDeletedFalse(userId);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(account), AccountExceptionEnum.ACCOUNT_NOT_EXIST);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(account.getOrganizationId()), AccountExceptionEnum.ACCOUNT_NOT_REGISTER);

        OrganizationDO organization = organizationDao.findByIdAndDeletedFalse(account.getOrganizationId());
        if (ObjectUtils.isEmpty(organization)) {
            log.info("账号: {} 绑定组织 {} 不存在", account.getId(), account.getOrganizationId());
            AssertUtil.assertTrue(!ObjectUtils.isEmpty(organization), AccountExceptionEnum.REGISTER_APPLYING);
        }
        if (OrganizationType.SINGLE.equals(organization.getType())) {
            QueryEntityDO entity = queryEntityDao.findByNameAndCodeAndTypeAndCreatorIdAndDeletedFalse(organization.getUsername(), organization.getIdNumber(), SearchType.PERSON, userId);
            QueryRecordDO queryRecord;
            if (!ObjectUtils.isEmpty(entity)) {
                queryRecord = queryRecordDao.findFirstByCreatorIdAndEntityIdAndDeletedFalse(userId, entity.getId());
            } else {
                SearchRecordContentDTO searchRecord = new SearchRecordContentDTO(organization.getUsername(), organization.getIdNumber(), organization.getPhone());
                String content = JSON.toJSONString(searchRecord);
                queryRecord = queryRecordDao.findByCreatorIdAndTypeAndContentAndDeletedFalse(userId, SearchType.PERSON, content);
            }
            SearchRecordContentDTO searchRecord = new SearchRecordContentDTO(organization.getUsername(), organization.getIdNumber(), organization.getPhone());
            String content = JSON.toJSONString(searchRecord);
            if (ObjectUtils.isEmpty(queryRecord)) {
                queryRecord = new QueryRecordDO();
                queryRecord.setCreatorId(userId);
                queryRecord.setContent(content);
                queryRecord.setType(SearchType.PERSON);
                if (!ObjectUtils.isEmpty(entity)) {
                    queryRecord.setEntityId(entity.getId());
                }
                queryRecord.setAuthorizedResult(AuthResultType.AUTHORIZED);
                queryRecordDao.save(queryRecord);
            }
            return queryRecord.getId();
        } else {
            // 查企业
            QueryEntityDO entity = queryEntityDao.findByNameAndTypeAndDeletedFalse(organization.getEnterName(), SearchType.ENTERPRISE);
            QueryRecordDO queryRecord;
            if (!ObjectUtils.isEmpty(entity)) {
                queryRecord = queryRecordDao.findFirstByCreatorIdAndEntityIdAndDeletedFalse(userId, entity.getId());
            } else {
                SearchRecordContentDTO searchRecord = new SearchRecordContentDTO(organization.getEnterName(), "", "");
                String content = JSON.toJSONString(searchRecord);
                queryRecord = queryRecordDao.findByCreatorIdAndTypeAndContentAndDeletedFalse(userId, SearchType.ENTERPRISE, content);
            }

            SearchRecordContentDTO searchRecord = new SearchRecordContentDTO(organization.getEnterName(), "", "");
            String content = JSON.toJSONString(searchRecord);
            if (ObjectUtils.isEmpty(queryRecord)) {
                queryRecord = new QueryRecordDO();
                queryRecord.setCreatorId(userId);
                queryRecord.setContent(content);
                queryRecord.setType(SearchType.ENTERPRISE);
                if (!ObjectUtils.isEmpty(entity)) {
                    queryRecord.setEntityId(entity.getId());
                }
                queryRecord.setAuthorizedResult(AuthResultType.AUTHORIZED);
                queryRecordDao.save(queryRecord);
            }
            return queryRecord.getId();
        }
    }

    private static void buildLitigationCaseData(SearchLitigationPageForm form, List<CaseLitigationVO> res, List<CaseDataDTO> cases, String caseCategory) {
        cases.forEach(data -> {
            CaseLitigationVO criminalCaseVO = new CaseLitigationVO();
            criminalCaseVO.setId(form.getId());
            criminalCaseVO.setCaseId(data.getN_ajbs());
            criminalCaseVO.setCaseNum(data.getC_ah());
            String n_laay_tree = data.getN_laay_tree();
            String[] n_laay_tree_arr = StringUtils.isNotBlank(data.getN_laay_tree()) ? n_laay_tree.split(",") : new String[0];
            criminalCaseVO.setCaseReason(n_laay_tree_arr.length > 0 ? n_laay_tree_arr[n_laay_tree_arr.length - 1] : "");
            criminalCaseVO.setLitigationStatus(data.getN_ssdw());
            criminalCaseVO.setStartTime(StringUtils.isBlank(data.getD_larq()) ? "" : data.getD_larq());
            criminalCaseVO.setEndTime(StringUtils.isBlank(data.getD_jarq()) ? "" : data.getD_jarq());
            criminalCaseVO.setCaseState(data.getN_ajjzjd());
            criminalCaseVO.setCaseType(data.getN_ajlx());
            criminalCaseVO.setCaseCategory(caseCategory);
            criminalCaseVO.setSettleWay(ObjectUtils.isEmpty(data.getN_jafs()) ? "" : data.getN_jafs());
            criminalCaseVO.setIsExample(false);
            res.add(criminalCaseVO);
        });
    }

    @Override
    public List<String> getCriminalQueryConditionCaseReason(Long userId, Long id) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(id);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);

        List<CaseLitigationVO> res = getLitigationCaseVOS(judicialStr);

        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        res = res.stream().filter(s -> !caseRemoveInfos.contains(s.getCaseNum())).collect(Collectors.toList());

        return res.stream().map(CaseLitigationVO::getCaseReason).filter(StringUtils::isNotBlank).distinct().collect(Collectors.toList());
    }

    private static List<CaseLitigationVO> getLitigationCaseVOS(String judicialInvolvementStr) {
        List<ResJudicialDataProdDTO> resJudicialData = JSON.parseArray(judicialInvolvementStr, ResJudicialDataProdDTO.class);
        ResJudicialDataProdDTO judicialResult = resJudicialData.get(0);
        Map<String, List<CaseDataDTO>> detailMap = judicialResult.getCaseData();

        SearchLitigationPageForm form = new SearchLitigationPageForm();
        List<CaseLitigationVO> res = new ArrayList<>();

        for (String category : CaseCategory.getCaseCategoryCode()) {
            List<CaseDataDTO> cases = detailMap.get(category);
            if (!CollectionUtils.isEmpty(cases)) {
                buildLitigationCaseData(form, res, cases, category);
            }
        }

        return res;
    }

    @Override
    public List<String> getCriminalQueryConditionCaseType(Long userId, Long id) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(id);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);

        List<CaseLitigationVO> res = getLitigationCaseVOS(judicialStr);

        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        res = res.stream().filter(s -> !caseRemoveInfos.contains(s.getCaseNum())).collect(Collectors.toList());

        return res.stream().map(CaseLitigationVO::getCaseType).distinct().collect(Collectors.toList());
    }

    @Override
    public Map getCaseInfo(Long userId, GetCaseInfoForm form) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        QueryType queryType = SearchType.ENTERPRISE.equals(entity.getType()) ? QueryType.ENT_JUDICIAL : QueryType.PER_JUDICIAL;
        String judicialStr = checkResultService.getJsonDataProd(userId, queryType, searchRecord, entity);

        List<ResJudicialDataProdDTO> resJudicialData = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
        ResJudicialDataProdDTO judicialResult = resJudicialData.get(0);
        Map<String, List<CaseDataDTO>> detailMap = judicialResult.getCaseData();
        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        detailMap.forEach((key, value) -> value.removeIf(caseDataDTO -> caseRemoveInfos.contains(caseDataDTO.getC_ah())));

        if (CollectionUtils.isEmpty(detailMap.get(form.getCaseCategory()))) {
            return Collections.emptyMap();
        }

        List<CaseDataDTO> cases = detailMap.get(form.getCaseCategory());

        if (!CollectionUtils.isEmpty(cases)) {
            CaseDataDTO caseStr = cases.stream().filter(data -> form.getCaseId().equals(data.getN_ajbs())).findFirst().orElse(new CaseDataDTO());
            return JSON.parseObject(GSON.toJson(caseStr), new TypeReference<Map<String, Object>>() {
            });
        }

        return Collections.emptyMap();
    }

    @Override
    public PageVO<LimitHighDataVO> searchLimitHighPage(Long userId, GetQueryInfoForm form, Pageable pageable) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);
//        String limitStr = checkResultService.getJsonData(userId, QueryType.PER_LIMIT, searchRecord, entity);
        LimitHighDataVO example = new LimitHighDataVO("无", "无", "无", "无案号", "无", "无", "无", true);

        if (StringUtils.isBlank(judicialStr)) {
            return new PageVO<>(0L, Collections.singletonList(example));
        }

        List<ResJudicialDataProdDTO> resultJson = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
        ResJudicialDataProdDTO judicialResult = resultJson.get(0);
        List<LimitHighDataDTO> limitHighData = Optional.ofNullable(judicialResult.getXg()).map(ResLimitDataDTO::getXgbzxr_current).orElse(new ArrayList<>());

        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        limitHighData = limitHighData.stream().filter(s -> !caseRemoveInfos.contains(s.getAh())).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(limitHighData)) {
            return new PageVO<>(0L, Collections.singletonList(example));
        }

        long total = limitHighData.size();
        List<LimitHighDataVO> res = limitHighData.stream().map(data -> {
            LimitHighDataVO vo = new LimitHighDataVO();
            BeanUtils.copyProperties(data, vo);
            vo.setIsExample(false);
            return vo;
        }).collect(Collectors.toList());

        return CollectionUtils.isEmpty(res) ? new PageVO<>(0L, Collections.singletonList(example)) : new PageVO<>(total, PageUtil.getPage(res, pageable));
    }

    @Override
    public PageVO<DishonestInfoDataVO> searchDishonestInfoPage(Long userId, GetQueryInfoForm form, Pageable pageable) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);
//        String dishonestInfoStr = checkResultService.getJsonData(userId, QueryType.PER_DISHONEST, searchRecord, entity);
        DishonestInfoDataVO example = new DishonestInfoDataVO("无", "无", "无", "无", "无案号", "无", "无", "无", "无", "无", "无", "无", "无", "无", "无", "无", true);

        if (StringUtils.isBlank(judicialStr)) {
            return new PageVO<>(0L, Collections.singletonList(example));
        }

        List<ResJudicialDataProdDTO> resultJson = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
        ResJudicialDataProdDTO judicialResult = resultJson.get(0);
        List<DishonestDataDTO> dishonestData = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_current).orElse(new ArrayList<>());

        List<String> caseRemoveInfos = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).
                collect(Collectors.toList());
        dishonestData = dishonestData.stream().filter(s -> !caseRemoveInfos.contains(s.getAh())).collect(Collectors.toList());

        if (CollectionUtils.isEmpty(dishonestData)) {
            return new PageVO<>(0L, Collections.singletonList(example));
        }

        long total = dishonestData.size();
        List<DishonestInfoDataVO> res = dishonestData.stream().map(data -> {
            DishonestInfoDataVO vo = new DishonestInfoDataVO();
            BeanUtils.copyProperties(data, vo);
            vo.setIsExample(false);
            return vo;
        }).collect(Collectors.toList());

        return CollectionUtils.isEmpty(res) ? new PageVO<>(0L, Collections.singletonList(example)) : new PageVO<>(total, PageUtil.getPage(res, pageable));
    }

    @Override
    public CheckPersonReportVO getReport(Long userId, GetQueryInfoForm form) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(form.getId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);

        CheckPersonReportVO res = new CheckPersonReportVO();
        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);

        String badRecordStr = checkResultService.getJsonDataProd(userId, QueryType.PER_BAD_RECORD, searchRecord, entity);
        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);
//        String limitStr = checkResultService.getJsonData(userId, QueryType.PER_LIMIT, searchRecord, entity);
//        String dishonestInfoStr = checkResultService.getJsonData(userId, QueryType.PER_DISHONEST, searchRecord, entity);

        String number = UUID.randomUUID().toString().replaceAll("-", "");
        AccountDO account = accountDao.findByIdAndDeletedFalse(userId);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(account), AccountExceptionEnum.ACCOUNT_NOT_EXIST);
        OrganizationDO organization = organizationDao.findByIdAndDeletedFalse(account.getOrganizationId());
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(organization), OrganizationExceptionEnum.ORGANIZATION_NOT_EXIST);

        String company = OrganizationType.ENTER.equals(organization.getType()) ? organization.getEnterName() : account.getUsername();
        PerReportInfoDTO basic = new PerReportInfoDTO(company, account.getUsername(), searchRecord.getName(), searchRecord.getIdNumber(), queryRecord.getAuthorizedTime(), number);
        PerReportBriefDTO brief = new PerReportBriefDTO();
        PerReportCaseDTO criminal = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO civil = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO jurisdiction = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO preservation = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO administrative = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO implement = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO bankrupt = new PerReportCaseDTO(0, 0, 0);
        PerReportCaseDTO compensate = new PerReportCaseDTO(0, 0, 0);
        List<PerReportLimitDTO> limit = new ArrayList<>();
        PerReportDishonestDTO dishonest = new PerReportDishonestDTO();

        brief.setIsIdAuthorizePass(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult())
                ? IdAuthorizeState.PASS : IdAuthorizeState.TO_VERIFY);
        if (StringUtils.isNotBlank(badRecordStr)) {
            List<ResBadRecordDTO> data = JSON.parseArray(badRecordStr, ResBadRecordDTO.class);
            ResBadRecordDTO personResult = data.get(0);
            brief.setBadRecordNum(BadRecordRiskLevelType.fromValue(StringUtils.isBlank(personResult.getRisk()) ? "" : personResult.getRisk()));
        }
        if (StringUtils.isNotBlank(judicialStr)) {
            List<ResJudicialDataProdDTO> resultJson = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
            ResJudicialDataProdDTO judicialResult = resultJson.get(0);
            Map<String, CaseNumDTO> countMap = judicialResult.getCaseNum();
            Map<String, List<CaseDataDTO>> detailMap = judicialResult.getCaseData();

            List<String> caseNum = caseRemoveDao.findCaseRemoveInfos().stream().map(CaseRemoveDO::getCaseNum).collect(Collectors.toList());
            int total = 0;
            int notClose = 0;
            int close = 0;
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.CRIMINAL.getCode()))) {
                criminal = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
                brief.setCriminalNum(0);
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.CRIMINAL.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.CRIMINAL.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setCriminalNum(caseNumInfo.getTotal() > total ? caseNumInfo.getTotal() - total : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() > total ? caseNumInfo.getTotal() - total : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() > close ? caseNumInfo.getClose() - close : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() >= notClose ? caseNumInfo.getNotClose() - notClose : 0);
                criminal = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.CIVIL.getCode()))) {
                civil = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
                brief.setCivilNum(0);
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.CIVIL.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.CIVIL.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setCivilNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose >= 0 ? caseNumInfo.getNotClose() : 0);
                civil = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.JURISDICTION.getCode()))) {
                jurisdiction = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
                brief.setJurisdictionNum(0);
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.JURISDICTION.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.JURISDICTION.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setJurisdictionNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose > 0 ? caseNumInfo.getNotClose() : 0);
                jurisdiction = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.PRESERVATION.getCode()))) {
                brief.setPreservationNum(0);
                preservation = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.PRESERVATION.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.PRESERVATION.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setPreservationNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose > 0 ? caseNumInfo.getNotClose() : 0);
                preservation = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.ADMINISTRATIVE.getCode()))) {
                brief.setAdministrativeNum(0);
                administrative = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.ADMINISTRATIVE.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.ADMINISTRATIVE.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setAdministrativeNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose > 0 ? caseNumInfo.getNotClose() : 0);
                administrative = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.IMPLEMENT.getCode()))) {
                brief.setImplementNum(0);
                implement = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.IMPLEMENT.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.IMPLEMENT.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setImplementNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose > 0 ? caseNumInfo.getNotClose() : 0);
                implement = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.BANKRUPT.getCode()))) {
                brief.setBankruptNum(0);
                bankrupt = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.BANKRUPT.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.BANKRUPT.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setBankruptNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose > 0 ? caseNumInfo.getNotClose() : 0);
                bankrupt = new PerReportCaseDTO(caseNumInfo);
                total = 0;
                notClose = 0;
                close = 0;
            }
            if (ObjectUtils.isEmpty(countMap.get(CaseCategory.COMPENSATE.getCode()))) {
                brief.setCompensateNum(0);
                compensate = new PerReportCaseDTO(new CaseNumDTO(0, 0, 0));
            } else {
                CaseNumDTO caseNumInfo = countMap.get(CaseCategory.COMPENSATE.getCode());
                List<CaseDataDTO> caseDetailInfos = detailMap.get(CaseCategory.COMPENSATE.getCode());
                for (CaseDataDTO caseDetailInfo : caseDetailInfos) {
                    if (caseNum.contains(caseDetailInfo.getC_ah())) {
                        total++;
                        if (StringUtils.isNotBlank(caseDetailInfo.getD_jarq())) {
                            close++;
                        } else {
                            notClose++;
                        }
                    }
                }
                brief.setCompensateNum(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setTotal(caseNumInfo.getTotal() - total > 0 ? caseNumInfo.getTotal() : 0);
                caseNumInfo.setClose(caseNumInfo.getClose() - close > 0 ? caseNumInfo.getClose() : 0);
                caseNumInfo.setNotClose(caseNumInfo.getNotClose() - notClose > 0 ? caseNumInfo.getNotClose() : 0);
                compensate = new PerReportCaseDTO(caseNumInfo);
            }

//            criminal = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.CRIMINAL.getCode(), new CaseNumDTO(0, 0, 0)));
//            civil = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.CIVIL.getCode(), new CaseNumDTO(0, 0, 0)));
//            jurisdiction = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.JURISDICTION.getCode(), new CaseNumDTO(0, 0, 0)));
//            preservation = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.PRESERVATION.getCode(), new CaseNumDTO(0, 0, 0)));
//            administrative = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.ADMINISTRATIVE.getCode(), new CaseNumDTO(0, 0, 0)));
//            implement = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.IMPLEMENT.getCode(), new CaseNumDTO(0, 0, 0)));
//            bankrupt = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.BANKRUPT.getCode(), new CaseNumDTO(0, 0, 0)));
//            compensate = new PerReportCaseDTO(countMap.getOrDefault(CaseCategory.COMPENSATE.getCode(), new CaseNumDTO(0, 0, 0)));
//
//            brief.setCriminalNum(countMap.getOrDefault(CaseCategory.CRIMINAL.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setCivilNum(countMap.getOrDefault(CaseCategory.CIVIL.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setJurisdictionNum(countMap.getOrDefault(CaseCategory.JURISDICTION.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setPreservationNum(countMap.getOrDefault(CaseCategory.PRESERVATION.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setAdministrativeNum(countMap.getOrDefault(CaseCategory.ADMINISTRATIVE.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setImplementNum(countMap.getOrDefault(CaseCategory.IMPLEMENT.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setBankruptNum(countMap.getOrDefault(CaseCategory.BANKRUPT.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());
//            brief.setCompensateNum(countMap.getOrDefault(CaseCategory.COMPENSATE.getCode(), new CaseNumDTO(0, 0, 0)).getTotal());

            int removeNum = 0;
            int historyNum = 0;
            // 限高
            int limitNum = Optional.ofNullable(judicialResult.getXg()).map(ResLimitDataDTO::getXgbzxr_count)
                    .map(ResLimitDataDTO.LimitCount::getCount_current).orElse(0);
            List<LimitHighDataDTO> limitHighData = Optional.ofNullable(judicialResult.getXg()).map(ResLimitDataDTO::getXgbzxr_current).orElse(new ArrayList<>());
            for (LimitHighDataDTO limitHighDatum : limitHighData) {
                if (caseNum.contains(limitHighDatum.getAh())) {
                    removeNum++;
                }
            }
            brief.setLimitNum(Math.max(limitNum - removeNum, 0));

            limitHighData = limitHighData.stream().filter(s -> !caseNum.contains(s.getAh())).collect(Collectors.toList());
            limit = limitHighData.stream().map(data -> {
                PerReportLimitDTO limitData = new PerReportLimitDTO();
                BeanUtils.copyProperties(data, limitData);
                return limitData;
            }).collect(Collectors.toList());
            removeNum = 0;

            // 失信
            int current = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_count)
                    .map(ResDishonestDataDTO.DishonestCount::getCount_current).orElse(0);
            int countTotal = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_count)
                    .map(ResDishonestDataDTO.DishonestCount::getCount_total).orElse(0);
            List<DishonestDataDTO> currentDishonestData = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_current).orElse(new ArrayList<>());
            List<DishonestDataDTO> historyDishonestData = Optional.ofNullable(judicialResult.getSx()).map(ResDishonestDataDTO::getSxbzxr_removed).orElse(new ArrayList<>());
            for (DishonestDataDTO dishonestDatum : currentDishonestData) {
                if (caseNum.contains(dishonestDatum.getAh())) {
                    removeNum++;
                }
            }
            for (DishonestDataDTO dishonestDatum : historyDishonestData) {
                if (caseNum.contains(dishonestDatum.getAh())) {
                    historyNum++;
                }
            }
            current = Math.max(current - removeNum, 0);
            countTotal = Math.max(countTotal - removeNum - historyNum, 0);
            brief.setDishonestNum(current);
            dishonest.setCurrent(current);
            dishonest.setHistory(countTotal - current);
        }

//        if (StringUtils.isNotBlank(limitStr)) {
//            List<ResLimitDataDTO> resultJson = JSON.parseArray(limitStr, ResLimitDataDTO.class);
//            int limitNum = Optional.ofNullable(resultJson.get(0)).map(ResLimitDataDTO::getXgbzxr_count)
//                    .map(ResLimitDataDTO.LimitCount::getCount_current).orElse(0);
//            brief.setLimitNum(limitNum);
//
//            List<LimitHighDataDTO> limitHighData = Optional.ofNullable(resultJson.get(0)).map(ResLimitDataDTO::getXgbzxr_current).orElse(new ArrayList<>());
//            limit = limitHighData.stream().map(data -> {
//                PerReportLimitDTO limitData = new PerReportLimitDTO();
//                BeanUtils.copyProperties(data, limitData);
//                return limitData;
//            }).collect(Collectors.toList());
//        }

//        if (StringUtils.isNotBlank(dishonestInfoStr)) {
//            List<ResDishonestDataDTO> resultJson = JSON.parseArray(dishonestInfoStr, ResDishonestDataDTO.class);
//            int current = Optional.ofNullable(resultJson.get(0)).map(ResDishonestDataDTO::getSxbzxr_count)
//                    .map(ResDishonestDataDTO.DishonestCount::getCount_current).orElse(0);
//            int total = Optional.ofNullable(resultJson.get(0)).map(ResDishonestDataDTO::getSxbzxr_count)
//                    .map(ResDishonestDataDTO.DishonestCount::getCount_total).orElse(0);
//            brief.setDishonestNum(current);
//
//            dishonest.setCurrent(current);
//            dishonest.setHistory(total - current);
//        }

        res.setBasic(basic);
        res.setBrief(brief);
        res.setCriminal(criminal);
        res.setCivil(civil);
        res.setJurisdiction(jurisdiction);
        res.setPreservation(preservation);
        res.setAdministrative(administrative);
        res.setImplement(implement);
        res.setBankrupt(bankrupt);
        res.setCompensate(compensate);
        res.setLimit(limit);
        res.setDishonest(dishonest);
        PersonRemoveDO personRemove = personRemoveDao.findInfoByIdNumber(searchRecord.getIdNumber());
        res.setIsShow(personRemove == null);
        return res;
    }

    @Override
    public void downloadReport(HttpServletResponse response, Long userId, Long id) {
        QueryRecordDO queryRecord = queryRecordDao.findByIdAndDeletedFalse(id);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
        AssertUtil.assertTrue(AuthResultType.AUTHORIZED.equals(queryRecord.getAuthorizedResult()), CheckPersonExceptionEnum.QUERY_AUTHORIZATION_NOT_PASS);
        AssertUtil.assertTrue(queryRecord.getType() == SearchType.PERSON, CheckPersonExceptionEnum.QUERY_TYPE_NOT_MATCH);
        AuthInfoDO authInfo = authInfoDao.findFirstByRelativeIdAndTypeOrderByCreateTimeDesc(queryRecord.getId(), AuthType.QUERY);
        SearchRecordContentDTO searchRecord = JSON.parseObject(queryRecord.getContent(), SearchRecordContentDTO.class);
        QueryEntityDO entity = checkResultService.getQueryEntity(userId, queryRecord, searchRecord);
        String badRecordStr = checkResultService.getJsonDataProd(userId, QueryType.PER_BAD_RECORD, searchRecord, entity);
        String judicialStr = checkResultService.getJsonDataProd(userId, QueryType.PER_JUDICIAL, searchRecord, entity);
        ResBadRecordDTO personResult = null;
        if (!StringUtils.isBlank(badRecordStr)) {
            List<ResBadRecordDTO> data = JSON.parseArray(badRecordStr, ResBadRecordDTO.class);
            personResult = data.get(0);
        }
        ResJudicialDataProdDTO judicialResult = null;
        if (!StringUtils.isBlank(judicialStr)) {
            List<ResJudicialDataProdDTO> data = JSON.parseArray(judicialStr, ResJudicialDataProdDTO.class);
            judicialResult = data.get(0);
        }

        List<CaseDataDTO> criminalInfos = new ArrayList<>();
        List<CaseDataDTO> civilInfos = new ArrayList<>();
        List<CaseDataDTO> administrativeInfos = new ArrayList<>();
        List<CaseDataDTO> preservationInfos = new ArrayList<>();
        List<CaseDataDTO> implementInfos = new ArrayList<>();
        List<CaseDataDTO> bankruptInfos = new ArrayList<>();
        List<CaseDataDTO> jurisdictionInfos = new ArrayList<>();
        List<CaseDataDTO> compensateInfos = new ArrayList<>();
        List<DishonestDataDTO> dishonestInfos = new ArrayList<>();
        List<LimitHighDataDTO> limitHighInfos = new ArrayList<>();
        int totalCase = 0;
        int criminalCase = 0;
        int civilCase = 0;
        int administrativeCase = 0;
        int preservationCase = 0;
        int implementCase = 0;
        int bankruptCase = 0;
        int jurisdictionCase = 0;
        int compensateCase = 0;
        int dishonestCase = 0;
        int limitHighCase = 0;
        if (judicialResult != null) {
            Map<String, List<CaseDataDTO>> detailMap = judicialResult.getCaseData();
            criminalInfos = detailMap.get(CaseCategory.CRIMINAL.getCode());
            civilInfos = detailMap.get(CaseCategory.CIVIL.getCode());
            administrativeInfos = detailMap.get(CaseCategory.ADMINISTRATIVE.getCode());
            preservationInfos = detailMap.get(CaseCategory.PRESERVATION.getCode());
            implementInfos = detailMap.get(CaseCategory.IMPLEMENT.getCode());
            bankruptInfos = detailMap.get(CaseCategory.BANKRUPT.getCode());
            jurisdictionInfos = detailMap.get(CaseCategory.JURISDICTION.getCode());
            compensateInfos = detailMap.get(CaseCategory.COMPENSATE.getCode());
            totalCase = criminalInfos.size() + civilInfos.size() + administrativeInfos.size() + preservationInfos.size() +
                    implementInfos.size() + bankruptInfos.size() + jurisdictionInfos.size() + compensateInfos.size();
            criminalCase = criminalInfos.size();
            civilCase = civilInfos.size();
            administrativeCase = administrativeInfos.size();
            preservationCase = preservationInfos.size();
            implementCase = implementInfos.size();
            bankruptCase = bankruptInfos.size();
            jurisdictionCase = jurisdictionInfos.size();
            compensateCase = compensateInfos.size();
            ResDishonestDataDTO sx = judicialResult.getSx();
            dishonestInfos = Optional.ofNullable(sx).map(ResDishonestDataDTO::getSxbzxr_current).orElse(new ArrayList<>());
            ResLimitDataDTO xg = judicialResult.getXg();
            limitHighInfos = Optional.ofNullable(xg).map(ResLimitDataDTO::getXgbzxr_current).orElse(new ArrayList<>());
            limitHighCase = limitHighInfos.size();
            dishonestCase = dishonestInfos.size();
            totalCase = totalCase + limitHighCase + dishonestCase;
        }

        XWPFDocument document = new XWPFDocument();

        addHeader(document);
        WordParagraph mainPage = getWordMainPage(searchRecord.getName());
        mainPage.addElement(document);
//        XWPFParagraph breakParagraph = document.createParagraph();
//        XWPFRun breakRun = breakParagraph.createRun();
//        breakRun.addBreak(BreakType.PAGE);
        getBasicInfo(document, searchRecord, authInfo, personResult);
        getLawCaseNumInfo(document, totalCase, criminalCase, civilCase, implementCase, jurisdictionCase, preservationCase, administrativeCase,
                bankruptCase, compensateCase, dishonestCase, limitHighCase, personResult);
        getCaseDetailInfo(document, criminalInfos, civilInfos, administrativeInfos, preservationInfos, implementInfos,
                bankruptInfos, jurisdictionInfos, compensateInfos, dishonestInfos, limitHighInfos);
        addFooter(document);
        // PdfUtil.docToPdf(document, "D:\\aad\\test.pdf");
        WordMaker.downLoadPdf("个人尽调报告", response, document);
    }

    private void addHeader(XWPFDocument document) {
        try {
            // 确保存在节属性
            CTSectPr sectPr = document.getDocument().getBody().getSectPr();
            if (sectPr == null) {
                sectPr = document.getDocument().getBody().addNewSectPr();
            }
            // 创建统一策略
            XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(document, sectPr);
            // 显式创建默认页眉
            if (policy.getDefaultHeader() == null) {
                policy.createHeader(STHdrFtr.DEFAULT);
            }
            // 获取已存在的页眉
            XWPFHeader header = policy.getDefaultHeader();
            // 清空原有内容（可选）
            header.clearHeaderFooter();
            // 添加页眉表格
            XWPFTable headerTable = header.createTable(1, 2);
            // 获取表格属性
            CTTblPr tblPr = headerTable.getCTTbl().getTblPr();
            // 创建或获取边框设置
            CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders();
            // 设置所有边框为隐藏（NIL）并清除线宽
            Arrays.asList(
                    borders.addNewTop(),
                    borders.addNewBottom(),
                    borders.addNewLeft(),
                    borders.addNewRight(),
                    borders.addNewInsideH(),
                    borders.addNewInsideV()
            ).forEach(border -> {
                border.setVal(STBorder.NIL); // 设置边框类型为无
                border.setSz(BigInteger.ZERO); // 设置边框尺寸为0
                border.setSpace(BigInteger.ZERO); // 设置边框间距为0
            });
            CTBorder bottomBorder = borders.addNewBottom();
            bottomBorder.setVal(STBorder.SINGLE);
            bottomBorder.setSz(BigInteger.valueOf(1)); // 加粗线
            bottomBorder.setColor("000000");
            headerTable.setWidth("100%"); // 表格宽度100%
            XWPFTableRow row = headerTable.getRow(0);
            row.setHeight(30 * 15);  // 30像素高度
            // 左侧单元格（图片）
            XWPFTableCell leftCell = headerTable.getRow(0).getCell(0);
            leftCell.setWidth("50%");
            // 从resources目录加载图片
            InputStream imageStream = getClass().getClassLoader().getResourceAsStream("back.png");
            XWPFRun imageRun = leftCell.addParagraph().createRun();
            imageRun.addPicture(imageStream,
                    XWPFDocument.PICTURE_TYPE_PNG,
                    "back.png",
                    Units.toEMU(100),  // 宽度100像素
                    Units.toEMU(30));  // 高度30像素
            // 右侧单元格（联系电话）
            XWPFTableCell rightCell = headerTable.getRow(0).getCell(1);
            rightCell.setWidth("50%");
            XWPFParagraph phonePara = rightCell.addParagraph();
            phonePara.setAlignment(ParagraphAlignment.RIGHT); // 右对齐
            CTTcPr ctTcPr = rightCell.getCTTc().addNewTcPr();
            CTVerticalJc vAlign = ctTcPr.addNewVAlign();
            vAlign.setVal(STVerticalJc.BOTTOM); // 垂直底部对齐
            XWPFRun phoneRun = phonePara.createRun();

            phoneRun.setText("联系电话：4008-400-610");
            phoneRun.setFontFamily("宋体");
            phoneRun.setFontSize(10);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private static void getCaseDetailInfo(XWPFDocument document, List<CaseDataDTO> criminalInfos, List<CaseDataDTO> civilInfos,
                                          List<CaseDataDTO> administrativeInfos, List<CaseDataDTO> preservationInfos, List<CaseDataDTO> implementInfos,
                                          List<CaseDataDTO> bankruptInfos, List<CaseDataDTO> jurisdictionInfos, List<CaseDataDTO> compensateInfos,
                                          List<DishonestDataDTO> dishonestInfos, List<LimitHighDataDTO> limitHighInfos) {
        WordParagraph threeTitle = WordParagraph.defaultHeading1("3.涉诉案件分析");
        threeTitle.addElement(document);
        WordParagraph threeOneTitle = WordParagraph.defaultHeading2("3.1重大案件");
        threeOneTitle.addElement(document);
        getCaseTableInfo(document, criminalInfos);
        WordParagraph threeTwoTitle = WordParagraph.defaultHeading2("3.2民事案件");
        threeTwoTitle.addElement(document);
        getCaseTableInfo(document, civilInfos);
        WordParagraph threeThreeTitle = WordParagraph.defaultHeading2("3.3行政案件");
        threeThreeTitle.addElement(document);
        getCaseTableInfo(document, administrativeInfos);
        WordParagraph threeFourTitle = WordParagraph.defaultHeading2("3.4非诉保全案件");
        threeFourTitle.addElement(document);
        getCaseTableInfo(document, preservationInfos);
        WordParagraph threeFiveTitle = WordParagraph.defaultHeading2("3.5执行案件");
        threeFiveTitle.addElement(document);
        getCaseTableInfo(document, implementInfos);
        WordParagraph threeSixTitle = WordParagraph.defaultHeading2("3.6强制清算与破产案件");
        threeSixTitle.addElement(document);
        getCaseTableInfo(document, bankruptInfos);
        WordParagraph threeSevenTitle = WordParagraph.defaultHeading2("3.7管辖案件");
        threeSevenTitle.addElement(document);
        getCaseTableInfo(document, jurisdictionInfos);
        WordParagraph threeEightTitle = WordParagraph.defaultHeading2("3.8赔偿案件");
        threeEightTitle.addElement(document);
        getCaseTableInfo(document, compensateInfos);
        WordParagraph threeNineTitle = WordParagraph.defaultHeading2("3.9风险记录");
        threeNineTitle.addElement(document);
        List<String> dishonestTitles = Arrays.asList("序号", "发布日期", "履行情况", "执行法院", "案号", "立案时间", "移除时间");
        XWPFTable oneTable = document.createTable(CollectionUtils.isEmpty(dishonestInfos) ? 1 : dishonestInfos.size() + 1, dishonestTitles.size());
        oneTable.setWidth("100%");
        for (int i = 0; i < dishonestTitles.size(); i++) {
            XWPFTableRow row = oneTable.getRow(0);
            row.setHeight(10);
            XWPFTableCell cell = row.getCell(i);
            //setCellStyle(cell, "D3D3D3", "FFFFFF", 10, "微软雅黑");
            //cell.setText(dishonestTitles.get(i));
            setCommonStyleYaHei(cell, dishonestTitles.get(i), 1);
        }
        for (int i = 0; i < dishonestInfos.size(); i++) {
            DishonestDataDTO dishonestData = dishonestInfos.get(i);
            XWPFTableRow row = oneTable.getRow(i + 1);
            row.setHeight(10);
            setCommonStyle(oneTable, i + 1);
            XWPFTableCell oneCell = row.getCell(0);
            oneCell.setText(String.valueOf(i + 1));
            XWPFTableCell twoCell = row.getCell(1);
            twoCell.setText(dishonestData.getFbrq());
            XWPFTableCell threeCell = row.getCell(2);
            threeCell.setText(dishonestData.getLxqk());
            XWPFTableCell fourCell = row.getCell(3);
            fourCell.setText(dishonestData.getZxfy());
            XWPFTableCell fiveCell = row.getCell(4);
            fiveCell.setText(dishonestData.getAh());
            XWPFTableCell sixCell = row.getCell(5);
            sixCell.setText(dishonestData.getLarq());
            XWPFTableCell sevenCell = row.getCell(6);
            sevenCell.setText(dishonestData.getYcrq());
        }
        WordParagraph threeTenTitle = WordParagraph.defaultHeading2("3.10限高记录");
        threeTenTitle.addElement(document);
        List<String> limitHighTitles = Arrays.asList("序号", "发布日期", "执行法院", "案号", "立案时间", "移除时间");
        XWPFTable twoTable = document.createTable(CollectionUtils.isEmpty(limitHighInfos) ? 1 : limitHighInfos.size() + 1, limitHighTitles.size());
        twoTable.setWidth("100%");
        for (int i = 0; i < limitHighTitles.size(); i++) {
            XWPFTableRow row = twoTable.getRow(0);
            row.setHeight(10);
            XWPFTableCell cell = row.getCell(i);
            //setCellStyle(cell, "D3D3D3", "FFFFFF", 10, "微软雅黑");
            //cell.setText(limitHighTitles.get(i));
            setCommonStyleYaHei(row.getCell(i), limitHighTitles.get(i), 1);
        }
        for (int i = 0; i < limitHighInfos.size(); i++) {
            LimitHighDataDTO limitHighData = limitHighInfos.get(i);
            XWPFTableRow row = twoTable.getRow(i + 1);
            row.setHeight(10);
            setCommonStyle(twoTable, i + 1);
            XWPFTableCell oneCell = row.getCell(0);
            oneCell.setText(String.valueOf(i + 1));
            XWPFTableCell twoCell = row.getCell(1);
            twoCell.setText(limitHighData.getFbrq());
            XWPFTableCell threeCell = row.getCell(2);
            threeCell.setText(limitHighData.getZxfy());
            XWPFTableCell fourCell = row.getCell(3);
            fourCell.setText(limitHighData.getAh());
            XWPFTableCell fiveCell = row.getCell(4);
            fiveCell.setText(limitHighData.getLarq());
            XWPFTableCell sixCell = row.getCell(5);
            sixCell.setText(limitHighData.getYcrq());
        }
    }

    private static void getCaseTableInfo(XWPFDocument document, List<CaseDataDTO> caseInfos) {
        List<String> tableTitles = Arrays.asList("序号", "案号", "经办法院", "案件进展阶段", "立案时间", "结案时间", "结案案由");
        XWPFTable oneTable = document.createTable(CollectionUtils.isEmpty(caseInfos) ? 1 : caseInfos.size() + 1, tableTitles.size());
        oneTable.setWidth("100%");
        XWPFTableRow oneRow = oneTable.getRow(0);
        oneRow.setHeight(10);
        for (int i = 0; i < tableTitles.size(); i++) {
            XWPFTableCell cell = oneRow.getCell(i);
            //setCellStyle(cell, "D3D3D3", "FFFFFF", 10, "微软雅黑");
            setCommonStyleYaHei(cell, tableTitles.get(i), 1);
            //cell.setText(tableTitles.get(i));
        }
        for (int i = 0; i < caseInfos.size(); i++) {
            XWPFTableRow row = oneTable.getRow(i + 1);
            setCommonStyle(oneTable, i + 1);
            CaseDataDTO caseData = caseInfos.get(i);
            XWPFTableCell firstCell = row.getCell(0);
            firstCell.setText(String.valueOf(i + 1));
            XWPFTableCell secondCell = row.getCell(1);
            secondCell.setText(caseData.getC_ah());
            XWPFTableCell thirdCell = row.getCell(2);
            thirdCell.setText(caseData.getN_jbfy());
            XWPFTableCell sixthCell = row.getCell(3);
            sixthCell.setText(caseData.getN_ajjzjd());
            XWPFTableCell seventhCell = row.getCell(4);
            seventhCell.setText(caseData.getD_larq());
            XWPFTableCell eighthCell = row.getCell(5);
            eighthCell.setText(caseData.getD_jarq());
            XWPFTableCell ninthCell = row.getCell(6);
            ninthCell.setText(caseData.getN_jaay());
        }
    }

    private static void getLawCaseNumInfo(XWPFDocument document, int totalCase, int criminalCase, int civilCase, int implementCase, int jurisdictionCase,
                                          int preservationCase, int administrativeCase, int bankruptCase, int compensateCase,
                                          int dishonestCase, int limitHighCase, ResBadRecordDTO personResult) {
        WordParagraph twoTitle = WordParagraph.defaultHeading1("2.统计概览");
        twoTitle.addElement(document);
        WordParagraph twoOneTitle = WordParagraph.defaultHeading2("2.1涉诉数据概览");
        twoOneTitle.addElement(document);
        XWPFTable oneTable = document.createTable(7, 4);
        // 设置全局样式
        oneTable.setWidth("100%"); // 表格宽度100%
        // 第一行：合并单元格并设置样式
        XWPFTableRow row0 = oneTable.getRow(0);
        mergeCellsHorizontal(oneTable, 0, 0, 3); // 合并第0行0-3列
        //setCellStyle(row0.getCell(0), "D3D3D3", "FFFFFF", 10, "微软雅黑");
        //setTableHeadStyleYaHei(row0.getCell(0), "涉诉数据概览");
        setCommonStyleYaHei(row0.getCell(0), "涉诉数据概览", 1);
        // 第二行：合并单元格
        XWPFTableRow row1 = oneTable.getRow(1);
        row1.setHeight(10);
        mergeCellsHorizontal(oneTable, 1, 0, 1); // 合并前两列
        mergeCellsHorizontal(oneTable, 1, 2, 3); // 合并后两列
        //row1.getCell(0).setText("案件总数");
        setCommonStyleYaHei(row1.getCell(0), "案件总数", 2);
        setCommonStyleYaHei(row1.getCell(2), totalCase + "", 2);
        //row1.getCell(2).setText(totalCase + "");

        // 后续行设置
        String[][] rowsContent = {
                {"重大案件记录", criminalCase == 0 ? "无" : criminalCase + "", "执行案件记录", implementCase == 0 ? "无" : implementCase + ""},
                {"管辖案件记录", jurisdictionCase == 0 ? "无" : jurisdictionCase + "", "非诉保全审查案件记录", preservationCase == 0 ? "无" : preservationCase + ""},
                {"行政案件记录", administrativeCase == 0 ? "无" : administrativeCase + "", "民事案件记录", civilCase == 0 ? "无" : civilCase + ""},
                {"强制清算与破产案件记录", bankruptCase == 0 ? "无" : bankruptCase + "", "赔偿案件记录", compensateCase == 0 ? "无" : compensateCase + ""},
                {"个人风险记录", dishonestCase == 0 ? "无" : dishonestCase + "", "限高记录", limitHighCase == 0 ? "无" : limitHighCase + ""}
        };
        for (int i = 0; i < rowsContent.length; i++) {
            XWPFTableRow row = oneTable.getRow(i + 2);
            row.setHeight(10);
            for (int j = 0; j < 4; j++) {
                row.getCell(j).setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); // 垂直居中
                XWPFParagraph p = row.getCell(j).getParagraphs().get(0);
                p.setSpacingBefore(0);
                p.setSpacingAfter(0);
                p.setAlignment(ParagraphAlignment.CENTER); // 水平居中
                XWPFRun r = p.createRun();
                r.setText(rowsContent[i][j]);
                r.setFontFamily("微软雅黑");
            }
            //setCommonStyle(oneTable, i + 2);
        }
        WordParagraph twoTwoTitle = WordParagraph.defaultHeading2("2.2不良记录概述");
        twoTwoTitle.addElement(document);
        XWPFTable twoTable = document.createTable(2, 2);
        // 获取表格属性
        CTTblPr tblPr = twoTable.getCTTbl().getTblPr();
        // 创建或获取边框设置
        CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders();
        // 去掉左边框和右边框
        borders.unsetLeft(); // 取消左侧外边框
        borders.unsetRight(); // 取消右侧外边框
        // 设置列宽
        twoTable.setWidth("100%");
        for (int i = 0; i < 2; i++) {
            XWPFTableRow row = twoTable.getRow(i);
            row.setHeight(10);
            row.getCell(0).setWidth("30%");
            row.getCell(1).setWidth("70%");
        }
        // 填充数据并设置格式
        Object[][] cellData = {
                {"不良风险", personResult == null ? "无风险" : (StringUtils.isBlank(personResult.getRisk()) ? "无风险" : personResult.getRisk())},
                {"风险标识说明", "无风险、低风险、中低风险、中风险、高风险、重大风险"}
        };
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2; j++) {
                XWPFTableCell cell = twoTable.getRow(i).getCell(j);
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); // 垂直居中

                XWPFParagraph p = cell.getParagraphs().get(0);
                p.setAlignment(ParagraphAlignment.CENTER); // 水平居中
                p.setSpacingBefore(0);
                p.setSpacingAfter(0);
                XWPFRun r = p.createRun();
                if (j == 0) {
                    r.setBold(true); // 加粗字体
                }
                r.setText(cellData[i][j].toString());
                r.setFontFamily("微软雅黑");
            }
        }
    }

    // 单元格合并方法
    private static void mergeCellsHorizontal(XWPFTable table, int row, int startCol, int endCol) {
        for (int cellIndex = startCol; cellIndex <= endCol; cellIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
            if (cellIndex == startCol) {
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    // 样式设置方法
    private static void setCellStyle(XWPFTableCell cell, String bgColor, String textColor,
                                     int fontSize, String fontFamily) {

        cell.setColor(bgColor);
        XWPFParagraph paragraph = cell.getParagraphs().get(0);
        paragraph.setAlignment(ParagraphAlignment.CENTER);
        XWPFRun run = paragraph.createRun();
        run.setText(cell.getText());
        run.setColor(textColor);
        run.setFontSize(fontSize);
        run.setFontFamily(fontFamily);
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
    }

    // 通用样式设置
    private static void setCommonStyle(XWPFTable table, int rowNum) {
        XWPFTableRow row = table.getRow(rowNum);
        for (int i = 0; i < row.getTableCells().size(); i++) {
            setCellStyle(row.getCell(i), "FFFFFF", "000000", 10, "微软雅黑");
        }
    }

    private static void setCommonStyleYaHei(XWPFTableCell cell, String text, int type) {
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); // 垂直居中
        if (type == 1) {
            cell.setColor("D3D3D3");
        }

        XWPFParagraph p = cell.getParagraphs().get(0);

        p.setSpacingBefore(0);
        p.setSpacingAfter(0);
        p.setAlignment(ParagraphAlignment.CENTER); // 水平居中
        XWPFRun r = p.createRun();
        r.setText(text);
        if (type == 1) {
            r.setBold(true);
        }

        r.setFontFamily("微软雅黑");
    }

    private static void setTableHeadStyleYaHei(XWPFTableCell cell, String text) {
        cell.setColor("D3D3D3");
        XWPFParagraph para = cell.addParagraph();
        para.setAlignment(ParagraphAlignment.CENTER);  // 水平居中
        cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        // 清除段落间距
        para.setSpacingBefore(0);
        para.setSpacingAfter(0);
        para.setSpacingLineRule(LineSpacingRule.EXACT);
        para.setSpacingBetween(0);

// 强制覆盖默认样式（避免 SpacingBefore/After）
        CTPPr ppr = para.getCTP().getPPr();
        if (ppr == null) {
            ppr = para.getCTP().addNewPPr();
        }
        CTSpacing spacing = ppr.isSetSpacing() ? ppr.getSpacing() : ppr.addNewSpacing();
        spacing.setBefore(BigInteger.valueOf(0));
        spacing.setAfter(BigInteger.valueOf(0));
        spacing.setLineRule(STLineSpacingRule.EXACT);  // 精确行距控制
        spacing.setLine(BigInteger.valueOf(240));     // 固定行高=12pt（适配中文）
        XWPFRun run = para.createRun();
        run.setText(text);
        run.setFontFamily("微软雅黑");
        run.setBold(true);
    }

    private static void getBasicInfo(XWPFDocument document, SearchRecordContentDTO searchRecord, AuthInfoDO authInfo, ResBadRecordDTO personResult) {
        WordParagraph oneTitle = WordParagraph.defaultHeading1("1.基本信息");
        oneTitle.addElement(document);
        XWPFTable table = document.createTable(4, 2);
        // 获取表格属性
        CTTblPr tblPr = table.getCTTbl().getTblPr();
        // 创建或获取边框设置
        CTTblBorders borders = tblPr.isSetTblBorders() ? tblPr.getTblBorders() : tblPr.addNewTblBorders();
        // 去掉左边框和右边框
        borders.unsetLeft(); // 取消左侧外边框
        borders.unsetRight(); // 取消右侧外边框
        // 设置列宽
        table.setWidth("100%");
        for (int i = 0; i < 4; i++) {
            XWPFTableRow row = table.getRow(i);
            row.setHeight(10);
            row.getCell(0).setWidth("30%");
            row.getCell(1).setWidth("70%");
        }
        // 填充数据并设置格式
        Object[][] cellData = {
                {"姓名", searchRecord.getName()},
                {"是否通过人脸核验", authInfo == null ? "未通过" : (authInfo.getPassed() == null ? "未通过" : (authInfo.getPassed() ? "通过" : "未通过"))},
                {"身份证号", searchRecord.getIdNumber()},
                {"风险标识", personResult == null ? "无风险" : (StringUtils.isBlank(personResult.getRisk()) ? "无风险" : personResult.getRisk())}
        };
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 2; j++) {
                XWPFTableCell cell = table.getRow(i).getCell(j);
                cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER); // 垂直居中
                XWPFParagraph p = cell.getParagraphs().get(0);
                p.setSpacingBefore(0);
                p.setSpacingAfter(0);
                p.setAlignment(ParagraphAlignment.CENTER); // 水平居中
                XWPFRun r = p.createRun();
                if (j == 0) {
                    r.setBold(true); // 加粗字体
                }
                r.setText(cellData[i][j].toString());
                r.setFontFamily("微软雅黑");
            }
        }
    }

    private static WordParagraph getWordMainPage(String name) {
        WordParagraph mainPage = new WordParagraph();
        List<WordText> texts = new LinkedList<>();
        WordText firstText = new WordText();
        firstText.setText("中舟数联（江苏）科技有限公司");
        firstText.setFontFamily("微软雅黑");
        firstText.setFontSize(14);
        texts.add(firstText);
        for (int i = 0; i < 15; i++) {
            WordText empty = new WordText();
            empty.setText("");
            empty.setAddCarriageReturn(true); // 添加回车换行
            texts.add(empty);
        }
        WordText secondText = new WordText();
        secondText.setText(name);
        secondText.setFontFamily("微软雅黑");
        secondText.setFontSize(62);
        secondText.setAddCarriageReturn(true);
        secondText.setColor("0000FF");
        secondText.setBold(true);

        WordText thirdText = new WordText();
        thirdText.setText("个人风险尽调报告");
        thirdText.setFontFamily("微软雅黑");
        thirdText.setFontSize(25);
        thirdText.setAddCarriageReturn(true);
        thirdText.setBold(true);

        SimpleDateFormat simpleDate = new SimpleDateFormat("yyyy年MM月dd日");
        Date date = new Date();
        String dateStr = simpleDate.format(date);
        WordText fourText = new WordText();
        fourText.setText(dateStr);
        fourText.setFontFamily("微软雅黑");
        fourText.setFontSize(16);
        texts.add(secondText);
        texts.add(thirdText);
        texts.add(fourText);
        for (int i = 0; i < 8; i++) {
            WordText empty = new WordText();
            empty.setText("");
            empty.setAddCarriageReturn(true); // 添加回车换行
            texts.add(empty);
        }
        WordText fiveText = new WordText();
        fiveText.setText("个人风险尽调报告依据候选人" + name + "签署的书面授权文件，中舟数联（江苏）科技有限公司依法对候选人进行个人风险尽调，相关数据通过合法合规渠道采集。");
        fiveText.setFontFamily("微软雅黑");
        fiveText.setFontSize(7);
        fiveText.setAddCarriageReturn(true);
        WordText sixText = new WordText();
        sixText.setText("本报告仅供商业决策参考之用，不构成诚信保对任何人之明示或暗示的观点或保证。您不得将本数据向任何第三方出售/向境外传输/在境外存储、使用；同时您不得利用本数据从事任何违法违规行为。否则，由此产生的一切后果由您自行承担。");
        sixText.setFontFamily("微软雅黑");
        sixText.setFontSize(7);
        sixText.setAddCarriageReturn(true);
        WordText sevenText = new WordText();
        sevenText.setText("我司声明: 报告内容基于原始数据整理，其使用后后果由您自行承担，我司不涉及任何法律责任。特此声明。");
        sevenText.setFontFamily("微软雅黑");
        sevenText.setFontSize(7);
        texts.add(fiveText);
        texts.add(sixText);
        texts.add(sevenText);
        mainPage.setTexts(texts);
        return mainPage;
    }

    public static void addFooter(XWPFDocument document) {
        // 创建页脚策略
        XWPFHeaderFooterPolicy headerFooterPolicy = document.createHeaderFooterPolicy();
        XWPFHeaderFooter footer = headerFooterPolicy.createFooter(STHdrFtr.DEFAULT);

        // 创建段落并居中
        XWPFParagraph footerParagraph = footer.createParagraph();
        footerParagraph.setAlignment(ParagraphAlignment.CENTER);

        // 创建 Run 并添加字段
        XWPFRun run = footerParagraph.createRun();
        run.setFontFamily("微软雅黑");
        run.setText("第 ");
        CTR ctr = run.getCTR();

        // 字段开始
        CTFldChar beginFld = ctr.addNewFldChar();
        beginFld.setFldCharType(STFldCharType.BEGIN);

        // 字段内容（PAGE）
        CTText instrText = ctr.addNewT();
        instrText.setStringValue("PAGE");
        instrText.setSpace(SpaceAttribute.Space.PRESERVE); // 直接设置空格属性

        // 字段结束
        CTFldChar endFld = ctr.addNewFldChar();
        endFld.setFldCharType(STFldCharType.END);

        // 添加 "页" 字
        run.setText(" 页");
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String uploadAuthorizedFile(Long accountId, MultipartFile file, SendAuthorizedCodeForm form) {
        AccountDO account = accountDao.findByIdAndDeletedFalse(accountId);
        AssertUtil.assertTrue(!ObjectUtils.isEmpty(account), AccountExceptionEnum.ACCOUNT_NOT_EXIST);

//        //判断文件格式
//        String fileName = file.getOriginalFilename();
//        String suffixName = fileName.substring(fileName.lastIndexOf("."));
//        if (!suffixName.matches("(?i)\\.(jpg|png|pdf|docx|doc)$")) {
//            throw new ServiceException(SysCode.FILE_FORMAT_ERROR);
//        }
//        String tempUrl = fileService.fileUpload(file, uploadAuthorizedTempPath);
//        String completeUrl = "https://admin.njxnet.com:8901/api/profile/" + tempUrl;
//        ArrayList<String> imgList = new ArrayList<>();
//        //如果是doc/dox/pdf格式先转换为图片
//        if (suffixName.matches("(?i)\\.(pdf|docx|doc)$")) {
//            Map<String,Object> paramMap = new HashMap<>();
//            paramMap.put("filePath",completeUrl);
//            String res = HttpUtil.post("https://fy.njxnet.com:8085/api/util/file2jpg",paramMap);
//            JSONObject json = JSON.parseObject(res);
//            if (json.getInteger("code") == 0) { // 判断是否成功
//                JSONArray dataArray = json.getJSONArray("data");
//                for (Object urlObj : dataArray) {
//                    imgList.add(urlObj.toString());
//                }
//            }else{
//                throw new ServiceException(SysCode.EXTERNAL_API_ERROR);
//            }
//
//        }else{
//            imgList.add(completeUrl);
//        }
//        Map<String, Object> requestBody = new HashMap<>();
//        requestBody.put("filePathList", imgList);
//        String jsonData = JSON.toJSONString(requestBody);
//        log.info("授权文件ocr请求参数：{}", jsonData);
//        String ocrData = HttpUtil.post("https://fy.njxnet.com:8085/api/ocr/commonOcr", jsonData);
//        log.info("授权文件ocr返回结果：{}", ocrData);
//        JSONObject ocrDataJson = JSON.parseObject(ocrData);
//
//        if (ocrDataJson.getInteger("code") == 0) { // 判断是否成功
//            String ocrContent = ocrDataJson.getString("data");
//            if(!ocrContent.contains(form.getName())){
//                throw new ServiceException(SysCode.FILE_CONTENT_VALID_ERROR);
//            }
//            if(!ocrContent.contains(form.getIdNumber())){
//                throw new ServiceException(SysCode.FILE_CONTENT_VALID_ERROR);
//            }
//            if((!ocrContent.contains("同意"))&&(!ocrContent.contains("授权"))){
//                throw new ServiceException(SysCode.FILE_CONTENT_VALID_ERROR);
//            }
//            if(!ocrContent.contains("背景调查")){
//                throw new ServiceException(SysCode.FILE_CONTENT_VALID_ERROR);
//            }
//        }else{
//            throw new ServiceException(SysCode.EXTERNAL_API_ERROR);
//        }
        String url = fileService.fileUpload(file, uploadAuthorizedPath);

        return url;
    }

    @Override
    public Long addAuthorizedRecord(Long accountId, AddPerAuthRecordForm form) {
        // 默认授权通过
//        QueryRecordDO queryRecord = queryRecordDao.findByCreatorIdAndTypeAndContentAndDeletedFalse(
//                accountId, SearchType.PERSON, JSON.toJSONString(new SearchRecordContentDTO(form.getName(), form.getIdNumber(), form.getPhone())));
//        AssertUtil.assertTrue(!ObjectUtils.isEmpty(queryRecord), CheckPersonExceptionEnum.QUERY_RECORD_NOT_EXIST);
//        queryRecord.setAuthorizedResult(AuthResultType.AUTHORIZED);
//        queryRecord.setCodeInfo(form.getCodeInfo());
//        queryRecord.setAuthorizedTime(new Timestamp(System.currentTimeMillis()));
//        queryRecordDao.save(queryRecord);


        // 创建查询记录
        SearchRecordContentDTO searchRecord = new SearchRecordContentDTO(form.getName(), form.getIdNumber(), form.getPhone());
        String content = JSON.toJSONString(searchRecord);
        //QueryRecordDO queryRecord = queryRecordDao.findByCreatorIdAndTypeAndContentAndDeletedFalse(accountId, SearchType.PERSON, content);
        boolean isUpdate = false;
        QueryRecordDO queryRecord = new QueryRecordDO();
        //if (ObjectUtils.isEmpty(queryRecord)) {
        queryRecord = new QueryRecordDO();
        queryRecord.setCreatorId(accountId);
        queryRecord.setContent(content);
        queryRecord.setType(SearchType.PERSON);
        queryRecord.setAuthorizedResult(AuthResultType.AUTHORIZED);
        //} else {
        Timestamp currentTime = new Timestamp(System.currentTimeMillis());
        queryRecord.setLatestDataTime(currentTime);
        queryRecord.setCreateTime(currentTime);

        isUpdate = true;
        //}

        QueryEntityDO entity;
        if (ObjectUtils.isEmpty(queryRecord.getEntityId())) {
            entity = queryEntityDao.findByNameAndCodeAndTypeAndCreatorIdAndDeletedFalse(searchRecord.getName(), searchRecord.getIdNumber(), SearchType.PERSON, accountId);
        } else {
            entity = queryEntityDao.findByIdAndDeletedFalse(queryRecord.getEntityId());
        }
        if (ObjectUtils.isEmpty(entity)) {
            entity = new QueryEntityDO(searchRecord.getName(), searchRecord.getIdNumber(), SearchType.PERSON);
            entity.setCreatorId(accountId);
            queryEntityDao.save(entity);
        }
        if (ObjectUtils.isEmpty(queryRecord.getEntityId()) || !queryRecord.getEntityId().equals(entity.getId())) {
            queryRecord.setEntityId(entity.getId());
        }
        //当前应该消耗的套餐类型，当前平台为Applet
        EndpointType endpointType = agentService.currentUseSearchTimeEndpoint(accountId, EndpointType.APPLET);
        if(endpointType.equals(EndpointType.H5)){
            String tradeNo = agentService.getOldestOrderTradeNo(accountId);
            queryRecord.setTradeNo(tradeNo);
        }

        queryRecordDao.save(queryRecord);

        if (isUpdate) {
            checkResultService.updateJsonDataProd(accountId, QueryType.PER_BAD_RECORD, searchRecord, entity.getId());
            checkResultService.updateJsonDataProd(accountId, QueryType.PER_JUDICIAL, searchRecord, entity.getId());
        }

        // 添加授权文件
        SysFileDO file = new SysFileDO();
        file.setName(form.getFileName());
        file.setUrl(form.getFileUrl());
        file.setType(form.getFileType());
        file.setSize(form.getFileSize());
        file.setRelativeId(queryRecord.getId());
        file.setRelativeType(FileRelativeType.PER_AUTH);
        fileDao.save(file);
        return queryRecord.getId();
    }

    @Override
    public Long personAuthQueryRecord(Long accountId, SendAuthorizedCodeForm form) {

        // 创建查询记录
        SearchRecordContentDTO searchRecord = new SearchRecordContentDTO(form.getName(), form.getIdNumber(), form.getPhone());
        String content = JSON.toJSONString(searchRecord);
        QueryRecordDO queryRecord = queryRecordDao.findByCreatorIdAndTypeAndContentAndDeletedFalse(accountId, SearchType.PERSON, content);
        if (ObjectUtils.isEmpty(queryRecord)) {
            queryRecord = new QueryRecordDO();
            queryRecord.setCreatorId(accountId);
            queryRecord.setContent(content);
            queryRecord.setType(SearchType.PERSON);
        } else {
            Timestamp currentTime = new Timestamp(System.currentTimeMillis());
            queryRecord.setLatestDataTime(currentTime);
            queryRecord.setCreateTime(currentTime);
        }
        queryRecord.setAuthorizedResult(AuthResultType.AUTHORIZED);
        QueryEntityDO entity;
        if (ObjectUtils.isEmpty(queryRecord.getEntityId())) {
            entity = queryEntityDao.findByNameAndCodeAndTypeAndCreatorIdAndDeletedFalse(searchRecord.getName(), searchRecord.getIdNumber(), SearchType.PERSON, accountId);
        } else {
            entity = queryEntityDao.findByIdAndDeletedFalse(queryRecord.getEntityId());
        }
        if (ObjectUtils.isEmpty(entity)) {
            entity = new QueryEntityDO(searchRecord.getName(), searchRecord.getIdNumber(), SearchType.PERSON);
            entity.setCreatorId(accountId);
            queryEntityDao.save(entity);
        }
        if (ObjectUtils.isEmpty(queryRecord.getEntityId()) || !queryRecord.getEntityId().equals(entity.getId())) {
            queryRecord.setEntityId(entity.getId());
        }
        queryRecordDao.save(queryRecord);
        return queryRecord.getId();
    }

}
